#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from com.chenxiaojie.dao.orm import create_args_string
from com.chenxiaojie.model.blog import Blog
from com.chenxiaojie.model.reply import Reply
from com.chenxiaojie.model.user import User
from com.chenxiaojie.mvc.blog_controller import text2html
from com.chenxiaojie.mvc.error import APIResourceNotFoundError, APIValueError
from com.chenxiaojie.mvc.mvc import get, delete, post, put
from com.chenxiaojie.mvc.page import page as Page


def get_page_index(page_str):
    p = 1
    try:
        p = int(page_str)
    except ValueError as e:
        pass
    if p < 1:
        p = 1
    return p


@get('/manage')
def manage():
    return 'redirect:/manage/replys.html'


@get('/manage/replys.html')
async def replys_page(*, page='1'):
    page_index = get_page_index(page)
    num = await Reply.findNumber('count(id)')
    p = Page(num, page_index)
    return {
        '__template__': 'manage_replys.html',
        'page_index': page_index,
        'page': p
    }


@get('/manage/reply/all')
async def all_reply(*, page='1'):
    page_index = get_page_index(page)
    num = await Reply.findNumber('count(id)')
    p = Page(num, page_index)
    if num == 0:
        return dict(page=p, comments=())
    replys = await Reply.findAll(orderBy='created_at desc', limit=(p.offset, p.limit))

    reply_creator_ids = set()
    for reply in replys:
        reply.html_content = text2html(reply.content)
        reply_creator_ids.add(reply.user_id)

    reply_creator_ids = list(reply_creator_ids)
    reply_creators = await User.findAll(where="id in (" + create_args_string(len(reply_creator_ids)) + ")",
                                        args=reply_creator_ids)
    for reply in replys:
        for creator in reply_creators:
            if reply.user_id == creator.id:
                reply.creator = creator

    return dict(page=p, replys=replys)


@delete('/manage/reply/{reply_id}')
async def delete_reply(reply_id):
    c = await Reply.find(reply_id)
    if c is None:
        raise APIResourceNotFoundError('Reply')
    await c.delete()
    return dict(id=reply_id)


@get('/manage/blogs.html')
async def blogs_page(*, page='1'):
    page_index = get_page_index(page)
    num = await Blog.findNumber('count(id)')
    p = Page(num, page_index)
    return {
        '__template__': 'manage_blogs.html',
        'page_index': page_index,
        'page': p
    }


@get('/manage/blog/all')
async def all_blog(*, page='1'):
    page_index = get_page_index(page)
    num = await Blog.findNumber('count(id)')
    p = Page(num, page_index)
    if num == 0:
        return dict(page=p, blogs=())
    blogs = await Blog.findAll(orderBy='created_at desc', limit=(p.offset, p.limit))

    creator_ids = set()
    for blog in blogs:
        creator_ids.add(blog.user_id)

    creator_ids = list(creator_ids)
    creators = await User.findAll(where="id in (" + create_args_string(len(creator_ids)) + ")", args=creator_ids)
    for blog in blogs:
        for creator in creators:
            if blog.user_id == creator.id:
                blog.creator = creator

    return dict(page=p, blogs=blogs)


@get('/manage/blog/create.html')
async def create_blog_page():
    return {
        '__template__': 'manage_blog_edit.html',
        'id': '',
        'action': '/manage/blog'
    }


@post('/manage/blog')
async def create_blog(request, *, title, summary, content):
    if not title or not title.strip():
        raise APIValueError('title', 'title cannot be empty.')
    if not summary or not summary.strip():
        raise APIValueError('summary', 'summary cannot be empty.')
    if not content or not content.strip():
        raise APIValueError('content', 'content cannot be empty.')
    blog = Blog(user_id=request.__user__.id, title=title.strip(), summary=summary.strip(), content=content.strip())
    return await blog.insert()


@get('/manage/blog/load/{id}')
async def get_blog(id):
    return await Blog.find(id)


@delete('/manage/blog/{id}')
async def delete_blog(id):
    blog = await Blog.find(id)
    if blog is None:
        raise APIResourceNotFoundError('Blog')
    await blog.delete()
    return dict(id=id)


@put('/manage/blog/{id}')
async def update_blog(id, *, title, summary, content):
    blog = await Blog.find(id)
    if blog is None:
        raise APIResourceNotFoundError('Blog')
    if not title or not title.strip():
        raise APIValueError('title', 'title cannot be empty.')
    if not summary or not summary.strip():
        raise APIValueError('summary', 'summary cannot be empty.')
    if not content or not content.strip():
        raise APIValueError('content', 'content cannot be empty.')
    blog.title = title.strip()
    blog.summary = summary.strip()
    blog.content = content.strip()
    try:
        return await blog.update()
    except RuntimeError as e:
        if str(e).find('affected rows: 0') == -1:
            raise


@get('/manage/blog/{blog_id}/edit.html')
async def edit_blog_page(*, blog_id):
    return {
        '__template__': 'manage_blog_edit.html',
        'id': blog_id,
        'action': '/manage/blog/%s' % blog_id
    }


@get('/manage/users.html')
async def manage_users(*, page='1'):
    page_index = get_page_index(page)
    num = await User.findNumber('count(id)')
    p = Page(num, page_index)
    return {
        '__template__': 'manage_users.html',
        'page_index': page_index,
        'page': p
    }


@get('/manage/user/all')
async def user_all(*, page='1'):
    page_index = get_page_index(page)
    num = await User.findNumber('count(id)')
    p = Page(num, page_index)
    if num == 0:
        return dict(page=p, users=())
    users = await User.findAll(orderBy='created_at desc', limit=(p.offset, p.limit))
    for u in users:
        u.passwd = '******'
    return dict(page=p, users=users)
